home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 16 / AMIGAplus Sonderheft 16 (1998)(ICP)(DE)[!].iso / pd / anwendungen / xpk_source / shell / xpk.c < prev    next >
C/C++ Source or Header  |  1998-08-27  |  8KB  |  370 lines

  1. #define NAME        "xPK"
  2. #define DISTRIBUTION    "(Freeware) "
  3. #define REVISION    "4"
  4.  
  5. /* Programmheader
  6.  
  7.     Name:        xPK
  8.     Author:        SDI (before 1.2 Urban Dominik Müller)
  9.     Distribution:    Freeware
  10.     Description:    General XPK file-to-file packer/unpacker
  11.     Compileropts:    -
  12.     Linkeropts:    -l xpkmaster
  13.  
  14.  1.0    : first public release
  15.  1.1    : docs written, version string added
  16.  1.2   19.10.96 : fixed an recursion error
  17.  1.3   29.11.96 : recompiled
  18.  1.4   28.11.97 : fixed little bug with chunk-hook
  19. */
  20.  
  21. #include "SDI_defines.h"
  22. #define SDI_TO_ANSI
  23. #include "SDI_ASM_STD_protos.h"
  24. #include <proto/exec.h>
  25. #include <proto/dos.h>
  26. #include <proto/xpkmaster.h>
  27. #include <exec/memory.h>
  28.  
  29. #ifdef __MAXON__
  30.   #define __asm
  31.   #define __saveds
  32. #endif
  33.  
  34. #define lines[1000]
  35.  
  36. ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *);
  37. STRPTR tempname(STRPTR);
  38. STRPTR basename(STRPTR);
  39. void   doarg(STRPTR);
  40. STRPTR dofile(STRPTR, struct FileInfoBlock *);
  41. void   end(STRPTR);
  42. LONG   isexecutable(STRPTR);
  43.  
  44. struct Hook         chunkhook    = {{0}, (ULONG (*) ()) chunkfunc};
  45. struct Library         *XpkBase    = 0;
  46. UBYTE            errbuf[300],
  47.             *err        = 0,
  48.             namebuf[200],
  49.             PrevName[100],
  50.             strbuf[200];
  51. struct FileInfoBlock     *fib        = 0;
  52.  
  53. UBYTE usage[] =
  54. "Usage: XPK [-efrsux] [-m method] [-p password] files\n"
  55. "       -e = extract files (same as -u)\n"
  56. "       -f = force packing of already packed files\n"
  57. "       -m = four letter packing method name\n"
  58. "       -p = encrypt/decrypt using password\n"
  59. "       -r = recursively (un)pack files in dir\n"
  60. "       -s = add suffix and don't delete original\n"
  61. "       -x = pack executables only\n";
  62.  
  63. UBYTE    suffix = 0, force = 0, unpack = 0, recurse = 0, depth = 0, executables = 0;
  64. STRPTR  password = 0, method = 0;
  65.  
  66. void main(int argc, char **argv)
  67. {
  68.   STRPTR c;
  69.   LONG i = 1;
  70.  
  71.   if(!(XpkBase = OpenLibrary(XPKNAME, 0)) ||
  72.   !(fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_ANY|MEMF_CLEAR)))
  73.     end("Cannot open " XPKNAME "\n");
  74.  
  75.   if(stricmp(basename(argv[0]), "XPK"))
  76.     method = basename(argv[0]);
  77.   else if(argc < 2 || !strcmp (argv[1], "?"))
  78.     end(usage);
  79.  
  80.   for(; *argv[i] == '-'; i++)
  81.     for(c = argv[i] + 1; *c; c++)
  82.     {
  83.       switch (*c)
  84.       {
  85.       case 'p': password = argv[++i]; break;
  86.       case 'm': method = argv[++i]; break;
  87.       case 's': suffix = 1; break;
  88.       case 'f': force = 1; break;
  89.       case 'e':
  90.       case 'u':    unpack = 1; break;
  91.       case 'r': recurse = 1; break;
  92.       case 'x':    executables = 1; break;
  93.       default: end(usage);
  94.       }
  95.       if(i >= argc)
  96.     end(usage);
  97.     }
  98.  
  99.   if(!method && !unpack)
  100.     end("Need a packing method, use -m\n");
  101.  
  102.   if(i == argc)
  103.     end(usage);
  104.  
  105.   for(; i < argc && !err; i++)
  106.     doarg(argv[i]);
  107.  
  108.   end(err);
  109. }
  110.  
  111. void iprint(STRPTR s)
  112. {
  113.   ULONG out = Output(), i;
  114.   for(i = depth; i; --i)
  115.     Write(out, "  ", 2);
  116.   Write(out, s, strlen(s));
  117. }
  118.  
  119. void doarg(STRPTR name)
  120. {
  121.   ULONG lock;
  122.  
  123.   if(*name == 0xFF)
  124.     return;
  125.  
  126.   if(!(lock = Lock(name, ACCESS_READ)))
  127.   {
  128.     sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
  129.     return;
  130.   }
  131.  
  132.   if(!Examine(lock, fib))
  133.   {
  134.     UnLock(lock);
  135.     sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
  136.     return;
  137.   }
  138.  
  139.   if(fib->fib_DirEntryType < 0)
  140.   {
  141.     UnLock(lock);
  142.     dofile(name, fib);
  143.   }
  144.   else if(recurse)
  145.   {
  146.     ULONG prev;
  147.  
  148.     sprintf(strbuf, "Directory %s\n", name);
  149.     iprint(strbuf);
  150.     prev = CurrentDir(lock);
  151.     *PrevName = 0xFF;
  152.  
  153.     while(ExNext(lock, fib) && !err)
  154.     {
  155.       if(SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  156.     err = " *** Break";
  157.       else
  158.       {
  159.         STRPTR thisname;
  160.     ULONG i = strlen(fib->fib_FileName) + 1;
  161.  
  162.         if(!(thisname = (STRPTR) AllocMem(i, MEMF_ANY)))
  163.         {
  164.           Write(Output(), "Not enough memory\n", 18);
  165.           break;
  166.         }
  167.     CopyMem(fib->fib_FileName, thisname, i);
  168.     depth++;
  169.     doarg(PrevName);
  170.     depth--;
  171.     strcpy(PrevName, thisname);
  172.     FreeMem(thisname, i);
  173.       }
  174.     }
  175.     depth++;
  176.     doarg(PrevName);
  177.     depth--;
  178.     *PrevName = 0xFF;
  179.  
  180.     UnLock(CurrentDir(prev));
  181.   }
  182. }
  183.  
  184. STRPTR dofile(STRPTR filename, struct FileInfoBlock *fib)
  185. {
  186.   struct XpkFib xfib = {0};
  187.   UBYTE buf[100];
  188.   LONG len;
  189.  
  190.   if(!force || unpack)
  191.   {
  192.     if(XpkExamineTags(&xfib, XPK_InName, (ULONG) filename, TAG_DONE))
  193.     {
  194.       sprintf(buf, "Error examining %s\n", filename);
  195.       iprint(buf);
  196.       return 0;
  197.     }
  198.   }
  199.  
  200.   tempname(filename);
  201.   if(!unpack)
  202.   {
  203.     if(!force && xfib.xf_Type != XPKTYPE_UNPACKED)
  204.     {
  205.       sprintf(buf, "Skipping (already packed) %s\n", filename);
  206.       iprint(buf);
  207.       return 0;
  208.     }
  209.  
  210.     if(executables && !isexecutable(filename))
  211.       return 0;
  212.  
  213.     if(suffix)
  214.       sprintf(namebuf, "%s.xpk", filename);
  215.  
  216.     if(XpkPackTags(
  217.         XPK_InName, (ULONG) filename,
  218.     XPK_OutName, (ULONG) namebuf,
  219.     XPK_ChunkHook, (ULONG) &chunkhook,
  220.     XPK_GetError, (ULONG) errbuf,
  221.     XPK_PackMethod, (ULONG) method,
  222.     XPK_Password, (ULONG) password,
  223.     XPK_NoClobber, TRUE,
  224.     TAG_DONE))
  225.     {
  226.       ULONG i = strlen(errbuf);
  227.       errbuf[i] = '\n'; errbuf[i+1] = '\0';
  228.       return err = errbuf;
  229.     }
  230.   }
  231.   else
  232.   {
  233.     if(xfib.xf_Type != XPKTYPE_PACKED)
  234.     {
  235.       sprintf(buf, "Skipping (already unpacked) %s\n", filename);
  236.       iprint(buf);
  237.       return 0;
  238.     }
  239.  
  240.     len = strlen(filename);
  241.     suffix = 0;
  242.     if(len > 4 && !stricmp(filename + len - 5, ".xpk"))
  243.     {
  244.       strcpy(namebuf, filename);
  245.       namebuf[len - 5] = 0;
  246.       suffix = 1;
  247.     }
  248.  
  249.     if(XpkUnpackTags(
  250.     XPK_InName, (ULONG) filename,
  251.     XPK_FileName, (ULONG) filename,
  252.     XPK_OutName, (ULONG) namebuf,
  253.     XPK_ChunkHook, (ULONG) &chunkhook,
  254.     XPK_Password, (ULONG) password,
  255.     XPK_GetError, (ULONG) errbuf,
  256.     XPK_NoClobber, TRUE,
  257.     TAG_DONE))
  258.     {
  259.       ULONG i = strlen(errbuf);
  260.       errbuf[i] = '\n'; errbuf[i+1] = '\0';
  261.       return err = errbuf;
  262.     }
  263.   }
  264.  
  265.   if(!suffix)
  266.   {
  267.     if(!DeleteFile(filename))
  268.       return err = "Cannot delete input file\n";
  269.     if(!Rename(namebuf, filename))
  270.       return err = "Cannot rename tempfile\n";
  271.     if(*fib->fib_Comment && !SetComment(filename, fib->fib_Comment))
  272.       return err = "Cannot set original comment\n";
  273.     if(fib->fib_Protection && !SetProtection(filename, fib->fib_Protection))
  274.       return err = "Cannot set original protection bits\n";
  275.   }
  276. }
  277.  
  278. ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *prog)
  279. {
  280.   ULONG out = Output(), i;
  281.   UBYTE buf[180];
  282.  
  283.   if(prog->xp_Type == XPKPROG_START)
  284.     Write(out, "\033[0 p", 5);
  285.  
  286.   if(prog->xp_Type != XPKPROG_END)
  287.     sprintf(buf,
  288.          "%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\033[K\r",
  289.          prog->xp_PackerName, prog->xp_Activity, prog->xp_Done,
  290.          prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  291.   else
  292.     sprintf(buf,
  293.          "%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
  294.          prog->xp_PackerName, prog->xp_Activity, prog->xp_ULen / 1024,
  295.          prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  296.  
  297.   iprint(buf);
  298.  
  299.   if(prog->xp_Type == XPKPROG_END)
  300.     Write(out, "\033[1 p", 5);
  301.  
  302.   if((i = SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C))
  303.     Write(out, "\n", 1);
  304.  
  305.   return i;
  306. }
  307.  
  308. STRPTR tempname(STRPTR name)
  309. {
  310.   strcpy(namebuf, name);
  311.   for(name = namebuf + strlen (namebuf); name > namebuf; name--)
  312.     if(name[-1] == '/' || name[-1] == ':')
  313.       break;
  314.   sprintf(name, "tmp%lx", &name);
  315.   return namebuf;
  316. }
  317.  
  318. LONG isexecutable(STRPTR name)
  319. {
  320.   ULONG fh;
  321.   BPTR buf[5];
  322.   UBYTE msg[100];
  323.   LONG len;
  324.  
  325.   if(!(fh = Open(name, MODE_OLDFILE)))
  326.   {
  327.     sprintf(msg, "Cannot open %s\n", name);
  328.     iprint(msg);
  329.     return 0;
  330.   }
  331.   len = Read(fh, (void *) buf, 20);
  332.   Close(fh);
  333.  
  334.   if(len < 20 || buf[0] != 0x3f3 || buf[1] != 0)
  335.   {
  336.     sprintf(msg, "%s not executable\n", name);
  337.     iprint(msg);
  338.     return 0;
  339.   }
  340.  
  341.   if(buf[3] != 0 || buf[4] + 1 != buf[2])
  342.   {
  343.     sprintf(msg, "%s overlayed\n", name);
  344.     iprint(msg);
  345.     return 0;
  346.   }
  347.   return 1;
  348. }
  349.  
  350. STRPTR basename(STRPTR name)
  351. {
  352.   STRPTR ret = name;
  353.  
  354.   for(; *name; ++name)
  355.   {
  356.     if(*name == ':' || *name == '/')
  357.       ret = name + 1;
  358.   }
  359.   return ret;
  360. }
  361.  
  362. void end(STRPTR text)
  363. {
  364.   if(text)    Write(Output(), text, strlen(text));
  365.   if(XpkBase)    CloseLibrary(XpkBase);
  366.   if(fib)    FreeMem(fib, sizeof(struct FileInfoBlock));
  367.  
  368.   exit(text ? 10 : 0);
  369. }
  370.